home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / TUT06NEW.ZIP / TUT6.CPP < prev    next >
C/C++ Source or Header  |  1995-01-04  |  14KB  |  387 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. //                                                                         //
  3. // TUTPROG6.CPP - VGA Trainer Program 6 (in Turbo C++ 3.0)                 //
  4. //                                                                         //
  5. // "The VGA Trainer Program" is written by Denthor of Asphyxia. However it //
  6. // was limited to Pascal only in its first run.  All I have done is taken  //
  7. // his original release, translated it to C++ and touched up a few things. //
  8. // I take absolutely no credit for the concepts presented in this code and //
  9. // am NOT the person to ask for help if you are having trouble.            //
  10. //                                                                         //
  11. // Program Notes : This program demonstrates the advantages of             //
  12. //                 pregenerated arrays.                                    //
  13. //                                                                         //
  14. //                 The Compact memory model (-mc) seems to provide the     //
  15. //                 best results for this tutorial.  Remember, use this     //
  16. //                 memory model when you have little code and lots of      //
  17. //                 data.                                                   //
  18. //                                                                         //
  19. // Author        : Grant Smith (Denthor) - denthor@beastie.cs.und.ac.za    //
  20. // Translator    : Christopher G. Mann   - r3cgm@dax.cc.uakron.edu         //
  21. //                                                                         //
  22. // Last Modified : January 4, 1995                                         //
  23. //                                                                         //
  24. /////////////////////////////////////////////////////////////////////////////
  25.  
  26. //               //
  27. // INCLUDE FILES //
  28. //               //
  29.  
  30.   #include <conio.h>
  31.                // clrscr(), getch(), kbhit(), gotoxy(),
  32.                // directvideo
  33.   #include <dos.h>
  34.                // MK_FP, geninterrupt()
  35.   #include <iostream.h>
  36.                // cout, memset(), memmove()
  37.   #include <math.h>
  38.                // sin(), cos()
  39.   #include <stdlib.h>
  40.                // calloc(), free(), exit()
  41.  
  42. //           //
  43. // CONSTANTS //
  44. //           //
  45.  
  46.   const PI = 3.1415927;
  47.   const TABLESIZE = 900;
  48.  
  49. //                     //
  50. // FUNCTION PROTOTYPES //
  51. //                     //
  52.  
  53.   // UTILITY FUNCTIONS
  54.   void  SetMCGA();
  55.   void  SetText();
  56.   void  Cls(unsigned char Col);
  57.   void  Pal(unsigned char ColorNo, unsigned char R,
  58.         unsigned char G,       unsigned char B);
  59.   void  Putpixel(int x, int y, unsigned char Col);
  60.   void  WaitRetrace();
  61.   float rad(float theta);
  62.  
  63.   // MID-LEVEL FUNCTIONS
  64.   void  NormCirc();
  65.   void  LookupCirc();
  66.   void  PalPlay();
  67.  
  68. //                              //
  69. // GLOBAL VARIABLE DECLARATIONS //
  70. //                              //
  71.  
  72.   // pointer to the offset of the VGA memory
  73.   unsigned char *vga = (unsigned char *) MK_FP(0xA000, 0);
  74.  
  75.   // This is our temporary pallette.  We only use colors 1 to 20, so we
  76.   // only have variables for those ones.
  77.   unsigned char Pall[18][3];
  78.  
  79.  
  80. ///////////////////////////////////////////////////////////////////////////////
  81. //                                                                           //
  82. //                                MAIN FUNCTION                              //
  83. //                                                                           //
  84. ///////////////////////////////////////////////////////////////////////////////
  85.  
  86. void main() {
  87.  
  88.   int loop1;
  89.  
  90.   clrscr();
  91.   cout
  92.     << "Hi there! This program will demonstrate the usefullness of\n"
  93.     << "pregenerated arrays, also known as lookup tables. The program\n"
  94.     << "will first draw a spiral without using a lookup table, rotate\n"
  95.     << "the pallette until a key is pressed, the calculate the lookup\n"
  96.     << "table, then draw the same spiral using the lookup table.\n\n";
  97.   cout
  98.     << "This is merely one example for the wide range of uses of a\n"
  99.     << "lookup table.\n\n";
  100.   cout
  101.     << "Hit any key to contine ...";
  102.   getch();
  103.   SetMCGA();
  104.  
  105.   // This handy trick allows you to use gotoxy() and cout in graphics mode.
  106.   directvideo = 0;
  107.  
  108.   // This sets our pallette colors 0 to 17 with red values between 12 to 63.
  109.   for (loop1=0;loop1<18;loop1++) {
  110.     Pall[loop1][0] = ((loop1+1)*3)+9;
  111.     Pall[loop1][1] = 0;
  112.     Pall[loop1][2] = 0;
  113.   }
  114.  
  115.   WaitRetrace();
  116.  
  117.   // This sets the true pallette to variable Pall
  118.   for (loop1=0;loop1<18;loop1++)
  119.     // loop+1 (make sure to leave color 0 for black)
  120.     Pal(loop1+1,Pall[loop1][0],Pall[loop1][1],Pall[loop1][2]);
  121.  
  122.   // This draws a spiral without lookups
  123.   NormCirc();
  124.   while (!kbhit()) PalPlay();
  125.   getch(); // clear the keyboard buffer after kbhit()
  126.  
  127.   // This draws a spiral with lookups
  128.   LookupCirc();
  129.   while (!kbhit()) PalPlay();
  130.   getch();
  131.  
  132.   getch();
  133.   SetText();
  134.   cout
  135.     << "All done. This concludes the sixth sample program in the ASPHYXIA\n"
  136.     << "Training series. You may reach DENTHOR under the name of GRANT\n"
  137.     << "SMITH on the MailBox BBS, or leave a message to ASPHYXIA on the\n"
  138.     << "ASPHYXIA BBS. I am also an avid Connectix BBS user.\n"
  139.     << "Get the numbers from Roblist, or write to :\n"
  140.     << "             Grant Smith\n"
  141.     << "             P.O. Box 270\n"
  142.     << "             Kloof\n"
  143.     << "             3640\n"
  144.     << "I hope to hear from you soon!\n\n";
  145.   cout
  146.     << "Hit any key to exit ...";
  147.   getch();
  148.  
  149. }
  150.  
  151.  
  152. /////////////////////////////////////////////////////////////////////////////
  153. //                                                                         //
  154. // SetMCGA() - This function gets you into 320x200x256 mode.               //
  155. //                                                                         //
  156. /////////////////////////////////////////////////////////////////////////////
  157.  
  158. void SetMCGA() {
  159.   _AX = 0x0013;
  160.   geninterrupt (0x10);
  161. }
  162.  
  163.  
  164. /////////////////////////////////////////////////////////////////////////////
  165. //                                                                         //
  166. // SetText() - This function gets you into text mode.                      //
  167. //                                                                         //
  168. /////////////////////////////////////////////////////////////////////////////
  169.  
  170. void SetText() {
  171.   _AX = 0x0003;
  172.   geninterrupt (0x10);
  173. }
  174.  
  175. /////////////////////////////////////////////////////////////////////////////
  176. //                                                                         //
  177. // Cls() - This clears the screen to the specified color.                  //
  178. //                                                                         //
  179. /////////////////////////////////////////////////////////////////////////////
  180.  
  181. void Cls(unsigned char Col) {
  182.   memset(vga, Col, 0xffff);
  183. }
  184.  
  185.  
  186. /////////////////////////////////////////////////////////////////////////////
  187. //                                                                         //
  188. // Pal() - This sets the Red, Green, and Blue values of a certain color.   //
  189. //                                                                         //
  190. /////////////////////////////////////////////////////////////////////////////
  191.  
  192. void Pal(unsigned char ColorNo, unsigned char R,
  193.      unsigned char G,       unsigned char B) {
  194.  
  195.   outp (0x03C8,ColorNo); // here is the pallette color I want to set
  196.   outp (0x03C9,R);
  197.   outp (0x03C9,G);
  198.   outp (0x03C9,B);
  199.  
  200. }
  201.  
  202.  
  203. /////////////////////////////////////////////////////////////////////////////
  204. //                                                                         //
  205. // Putpixel() - This puts a pixel at X,Y using color Col, on VGA or the    //
  206. //              Virtual Screen;                                            //
  207. //                                                                         //
  208. /////////////////////////////////////////////////////////////////////////////
  209.  
  210. void Putpixel (int x, int y, unsigned char Col) {
  211.   memset(vga+x+(y*320),Col,1);
  212. }
  213.  
  214.  
  215. /////////////////////////////////////////////////////////////////////////////
  216. //                                                                         //
  217. // WaitRetrace() - This waits until you are in a Verticle Retrace.         //
  218. //                                                                         //
  219. /////////////////////////////////////////////////////////////////////////////
  220.  
  221. void WaitRetrace() {
  222.  
  223.   _DX = 0x03DA;
  224.  
  225.   l1: asm {
  226.     in  al,dx;
  227.     and al,0x08;
  228.     jnz l1;
  229.       }
  230.  
  231.   l2: asm {
  232.     in  al,dx;
  233.     and al,0x08;
  234.     jz  l2;
  235.       }
  236. }
  237.  
  238.  
  239. /////////////////////////////////////////////////////////////////////////////
  240. //                                                                         //
  241. // rad() - This calculates the degrees of an angle.                        //
  242. //                                                                         //
  243. /////////////////////////////////////////////////////////////////////////////
  244.  
  245. float rad(float theta) {
  246.   return ((theta * PI)/180);
  247. }
  248.  
  249.  
  250. /////////////////////////////////////////////////////////////////////////////
  251. //                                                                         //
  252. // NormCirc() - This generates a spiral without using a lookup table.      //
  253. //                                                                         //
  254. /////////////////////////////////////////////////////////////////////////////
  255.  
  256. void NormCirc() {
  257.  
  258.   int loop1,x,y;
  259.   float deg,radius;
  260.  
  261.   gotoxy(1,1);
  262.   cout << "Without pregenerated arrays.";
  263.  
  264.   for (loop1=60;loop1>42;loop1--) {
  265.     deg = 0.0;
  266.     radius = (float) loop1;
  267.  
  268.     do {
  269.       x = radius*cos(rad(deg));
  270.       y = radius*sin(rad(deg));
  271.       Putpixel(x+160,y+100,61-loop1);
  272.       deg += 0.4;          // Increase the degree so the circle is round
  273.       radius -= 0.019;     // Decrease the radius for a spiral effect
  274.  
  275.       // NOTE: If you change this last statement to "radius -= 0.02;" like
  276.       // the Pascal code has it, you will get holes in the spiral.  You
  277.       // get bonus credit if you can tell me why this is.
  278.  
  279.     }
  280.     while (radius >= 0.0); // continue until the radius is zero (at center)
  281.   }
  282. }
  283.  
  284.  
  285. /////////////////////////////////////////////////////////////////////////////
  286. //                                                                         //
  287. // LookupCirc() - This draws a spiral using a lookup table.                //
  288. //                                                                         //
  289. /////////////////////////////////////////////////////////////////////////////
  290.  
  291. void LookupCirc() {
  292.  
  293.   int x, y, pos, loop1;
  294.   float radius, deg;
  295.   float *costbl=NULL, *sintbl=NULL;
  296.  
  297.   // allocate memory for the two tables
  298.   costbl = (float *) calloc(TABLESIZE,sizeof(float));
  299.   sintbl = (float *) calloc(TABLESIZE,sizeof(float));
  300.  
  301.   // always check to see if enough memory was allocated
  302.   if ((costbl == NULL) || (sintbl == NULL)) {
  303.     SetText();
  304.     cout << "Insufficient memory for lookup tables, exiting...";
  305.     exit(1);
  306.   }
  307.  
  308.   Cls(0);
  309.   gotoxy(1,1);
  310.   cout << "Generating variables....";
  311.  
  312.   // There are 360 degrees in a circle.  If you increase the degrees by 0.4,
  313.   // the number of needed parts of the table is 360/0.4=900. (TABLESIZE)
  314.   //
  315.   // For greater accuracy I increase the degrees by 0.4, because if I
  316.   // increase them by one, holes are left in the final product as a
  317.   // result of the rounding error margin. This means the pregenerated array
  318.   // is bigger, takes up more memory and is slower to calculate, but
  319.   // the finished product looks better.
  320.  
  321.   deg = 0.0;
  322.   for (loop1=0;loop1<TABLESIZE;loop1++) {
  323.     costbl[loop1] = cos(rad(deg));
  324.     sintbl[loop1] = sin(rad(deg));
  325.     deg += 0.4;
  326.   }
  327.  
  328.   gotoxy(1,1);
  329.   cout << "With pregenerated arrays.";
  330.  
  331.   // NOTE: The spiral drawn with this function leaves a small piece missing
  332.   // on the right side.  It looks like a pie with a piece cut out.  You get
  333.   // extra credit if you can tell me why this is.
  334.  
  335.   for (loop1=60;loop1>42;loop1--) {
  336.     pos = 0;
  337.     radius = loop1;
  338.     do {
  339.       // Note how I am not recalculating sin and cos for each point.
  340.       x = radius*costbl[pos];
  341.       y = radius*sintbl[pos];
  342.       Putpixel(x+160,y+100,61-loop1);
  343.       // Decrease the radius for a spiral effect
  344.       radius -= 0.020;
  345.       // I only made a table from 1 to 900, so it must never exceed that,
  346.       // or the program will probably crash.  Go ahead and increment
  347.       // pos while you are at it (more compact but less readable). :)
  348.       if (++pos > TABLESIZE-1) pos = 0;
  349.     }
  350.     while (radius >= 0.0);
  351.   }
  352.  
  353.   // Freeing the memory taken up by the tables. This is very important.
  354.   free(costbl);
  355.   free(sintbl);
  356.  
  357. }
  358.  
  359.  
  360. /////////////////////////////////////////////////////////////////////////////
  361. //                                                                         //
  362. // PalPlay() - This function mucks about with our "virtual pallette", then //
  363. //             shoves it to the screen.                                    //
  364. //                                                                         //
  365. /////////////////////////////////////////////////////////////////////////////
  366.  
  367. void PalPlay() {
  368.  
  369.   // This is used as a "temporary color" in our pallette
  370.   unsigned char Tmp[3];
  371.   int loop1;
  372.  
  373.   // This copies color 0 from our virtual pallette to the Tmp variable.
  374.   memmove(Tmp,Pall[0],3);
  375.  
  376.   // This moves the entire virtual pallette down one color.
  377.   memmove(Pall[0],Pall[1],17*3);
  378.  
  379.   // This copies the Tmp variable to the bottom of the virtual pallette.
  380.   // Don't change 0: leave this always black to not change overscan color.
  381.   memmove(Pall[17],Tmp,3);
  382.  
  383.   WaitRetrace();
  384.   for (loop1=0;loop1<18;loop1++)
  385.    Pal(loop1+1,Pall[loop1][0], Pall[loop1][1], Pall[loop1][2]);
  386.  
  387. }